package com.movie.api.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.movie.api.mapper.ActorMapper;
import com.movie.api.mapper.FilmMapper;
import com.movie.api.mapper.FilmTimeMapper;
import com.movie.api.mapper.FilmVipMapper;
import com.movie.api.model.dto.EvaluateRankDto;
import com.movie.api.model.dto.PageDto;
import com.movie.api.model.entity.Film;
import com.movie.api.model.entity.FilmVip;
import com.movie.api.model.vo.FilmInfoAndStarVO;
import com.movie.api.model.vo.FilmInfoVO;
import com.movie.api.model.vo.FilmVO;
import com.movie.api.model.vo.PageResultVO;
import com.movie.api.service.FilmIsVipService;
import com.movie.api.service.FilmService;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
@CacheConfig(cacheNames = "film")
public class FilmServiceImpl implements FilmService {

    @Resource
    private FilmMapper filmMapper;
    @Resource
    private FilmVipMapper filmVipMapper;

    @Resource
    private FilmTimeMapper filmTimeMapper;

    @Resource
    private ActorMapper actorMapper;

    @Override
    public void save(Film film) {
        film.setHot(0);
        filmMapper.insert(film);
    }


    @Override
    public void deleteById(String id) {
        filmMapper.deleteById(id);
    }


    @Override
    public List<Film> findAll() {
        return filmMapper.selectList(null);
    }

    @Override
    public List<Film> findByRegionAndType(String region, String type) {
        QueryWrapper<Film> wrapper = new QueryWrapper<>();
        if (!region.equals("全部")) {
            wrapper.in("region", region);
        }
        if (!type.equals("全部")) {
            wrapper.in("type", type);
        }
        return filmMapper.selectList(wrapper);
    }

    @Override
    public List<Film> getFilmByTime(String time) {
        if (Objects.equals(time, "全部")) {
            return filmTimeMapper.getByAll();
        } else if (Objects.equals(time, "本周")) {
            return filmTimeMapper.getByWeek();
        } else if (Objects.equals(time, "本月")) {
            return filmTimeMapper.getByMonth();
        }
        return null;
    }

    @Override
    public void viewAt(Integer filmId) {
        filmTimeMapper.viewAt(filmId);
        filmTimeMapper.addhot(filmId);
    }

    @Override
    public List<FilmInfoVO> page(String selectedOption, String searchText) {
        List<Film> filmList;
        if (Objects.equals(selectedOption, "电影")) {
            filmList = filmTimeMapper.selectByName(searchText);
        } else if (Objects.equals(selectedOption, "导演")) {
            filmList = filmTimeMapper.selectByDirector(searchText);
        } else {
            filmList = filmTimeMapper.selectByActors(searchText);
        }
        List<FilmInfoVO> filmInfoVOList = new ArrayList<>();
        for (Film film : filmList) {
            FilmInfoVO e = new FilmInfoVO();
            BeanUtils.copyProperties(film, e);
            filmInfoVOList.add(e);
        }
        return filmInfoVOList;
    }

    @Cacheable
    @Override
    public PageResultVO pageList(PageDto pageDto) {
        Integer currentPage = pageDto.getCurrentPage();
        Integer pageSize = pageDto.getPageSize();
        int startIndex = (currentPage - 1) * pageSize;
        List<Film> pageByAll = null;
        if (pageDto.getTime().equals("全部")) {
            pageByAll = filmTimeMapper.getPageByAll(startIndex, pageSize);
        } else if (pageDto.getTime().equals("本月")) {
            pageByAll = filmTimeMapper.getPageByMonth(startIndex, pageSize);
        } else {
            pageByAll = filmTimeMapper.getPageByWeek(startIndex, pageSize);
        }
        List<FilmVO> filmVOList = new ArrayList<>();
        for (Film film : pageByAll) {
            FilmVO filmVO = new FilmVO();
            BeanUtils.copyProperties(film, filmVO);

            QueryWrapper<FilmVip> filmVipQueryWrapper = new QueryWrapper<>();
            String filmId = film.getId();
            int filmIdInt = Integer.parseInt(filmId);
            filmVipQueryWrapper.eq("film_id", filmIdInt);
            FilmVip filmVip = filmVipMapper.selectOne(filmVipQueryWrapper);
            Integer isVip = filmVip.getIsVip();
            boolean vip = true;
            if (isVip == 0) {
                vip = false;
            }
            filmVO.setVip(vip);
            filmVOList.add(filmVO);
        }

        PageResultVO pageResultVO = new PageResultVO();
        pageResultVO.setItems(filmVOList);
        pageResultVO.setTotal(filmTimeMapper.count());
        return pageResultVO;
    }

    @Override
    public PageResultVO getEvaluateRank(EvaluateRankDto pageDto) {
        Integer currentPage = pageDto.getCurrentPage();
        Integer pageSize = pageDto.getPageSize();
        int startIndex = (currentPage - 1) * pageSize;
        List<FilmInfoAndStarVO> pageByAll = filmTimeMapper.getFilmByComment(startIndex, pageSize);
        PageResultVO pageResultVO = new PageResultVO();
        pageResultVO.setItems(pageByAll);
        pageResultVO.setTotal(filmTimeMapper.count());
        return pageResultVO;
    }

    @Override
    public List<Film> findHots(Integer limit) {
        QueryWrapper<Film> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("hot").last("limit " + limit);
        return filmMapper.selectList(wrapper);
    }


    @Override
    public List<Film> findLikeName(String name) {
        QueryWrapper<Film> wrapper = new QueryWrapper<>();
        wrapper.like("name", name);
        return filmMapper.selectList(wrapper);
    }


    @Override
    public FilmInfoVO findById(String id) {
        Film film = filmMapper.selectById(id);
        FilmInfoVO filmInfoVO = new FilmInfoVO();
        BeanUtils.copyProperties(film, filmInfoVO);
        List<String> actors = actorMapper.getActors(filmInfoVO.getId());
        String join = String.join(",", actors);
        filmInfoVO.setActors(join);
        System.out.println(filmInfoVO);
        return filmInfoVO;
    }

    @Override
    public Film update(Film film) {
        filmMapper.updateById(film);
        return film;
    }

    // Impl

    /**
     * 根据电影类型，返回电影数量
     *
     * @return
     */

    @Override
    public List<Map<String, Object>> getCountByType() {
        // 查询出所有电影
        List<Film> filmList = filmMapper.selectList(null);
        Map<String, Long> collect = filmList.stream()
                .filter(film -> ObjectUtils.isNotEmpty(film.getType())) // 过滤：所有电影类型字段为空的都要过滤
                .collect(Collectors.groupingBy(Film::getType, Collectors.counting())); // 聚合：根据类型字段和数量分组聚合
        // 最后返回给前端的数据结构
        List<Map<String, Object>> mapList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(collect)) {
            for (String key : collect.keySet()) {
                // {value: 1048, name: 'Search Engine'},
                Map<String, Object> map = new HashMap<>();
                map.put("name", key);
                map.put("value", collect.get(key));
                mapList.add(map);
            }
        }
        return mapList;
    }

    /**
     * 根据电影类型，返回电影观看次数
     *
     * @return
     */

    @Override
    public Map<String, Object> getViewCountByType() {
        List<Map<String, Object>> resultList = filmTimeMapper.countViewsByType();
        List<String> xAxis = new ArrayList<>();
        List<Long> yAxis = new ArrayList<>();
        for (Map<String, Object> result : resultList) {
            xAxis.add((String) result.get("type"));
            yAxis.add(((Number) result.get("view_count")).longValue());
        }
        Map<String, Object> map = new HashMap<>();
        map.put("xAxis", xAxis);
        map.put("yAxis", yAxis);
        return map;
    }

    /**
     * 根据近七天每天，返回电影观看次数
     *
     * @return
     */
    public Map<String, Object> getViewCountByLastSevenDays() {
        List<Map<String, Object>> resultList = filmTimeMapper.countViewsLastSevenDays();
        List<String> xAxis = new ArrayList<>();
        List<Long> yAxis = new ArrayList<>();

        for (Map<String, Object> result : resultList) {
            String viewDate = (String) result.get("view_date");
            Long viewCount = ((Number) result.get("view_count")).longValue();
            xAxis.add(viewDate);
            yAxis.add(viewCount);
        }

        Map<String, Object> map = new HashMap<>();
        map.put("xAxis", xAxis);
        map.put("yAxis", yAxis);

        return map;
    }

    /**
     * 获取近30天电影数据（报表用）
     *
     * @return
     */
    public Map<String, Object> getLast30DaysMovieData() {
        // 获取查询日期

        // 获取电影播放的数据（已排序）
        List<Map<String, Object>> movieData = filmTimeMapper.getMovieViewsWithinLast30Days();
        return handleExcelReportData(movieData);
    }

    /**
     * 获取全部时间电影数据（报表用）
     *
     * @return
     */
    public Map<String, Object> getAllDaysMovieData() {

        // 获取电影播放的数据（已排序）
        List<Map<String, Object>> movieData = filmTimeMapper.getMovieViewsWithinAllDays();
        return handleExcelReportData(movieData);
    }

    private Map<String, Object> handleExcelReportData(List<Map<String, Object>> movieData) {
        // 计算总播放量，最高播放量和最低播放量
        long totalViews = 0;
        long maxViews = 0;
        long minViews = Long.MAX_VALUE;

        for (Map<String, Object> data : movieData) {
            long views = (long) data.get("views");
            totalViews += views;
            if (views > maxViews) maxViews = views;
            if (views < minViews) minViews = views;
        }

        // 构建概览数据
        Map<String, Object> summary = new HashMap<>();
        summary.put("totalViews", totalViews);
        summary.put("maxViews", maxViews);
        summary.put("minViews", minViews);

        // 排名处理：直接给map添加rank字段
        int rank = 1;
        for (Map<String, Object> data : movieData) {
            data.put("rank", rank++);
        }

        // 组合返回数据
        Map<String, Object> result = new HashMap<>();
        result.put("summary", summary);
        result.put("details", movieData);
        return result;
    }

}
